# Next.js

## Installation

> Next.js 13.2.1 or higher is required in order to use `react-tweet`.

Follow the [installation docs in the Introduction](/#installation).

## Usage

In any component, import `Tweet` from `react-tweet` and use it like so:

```tsx copy
import { Tweet } from 'react-tweet'

export default function Page() {
  return <Tweet id="1628832338187636740" />
}
```

`Tweet` works differently depending on where it's used. If it's used in the App Router it will fetch the tweet in the server. If it's used in the pages directory it will fetch the tweet in the client with [SWR](https://swr.vercel.app/).

You can learn more about `Tweet` in the [Twitter theme docs](/twitter-theme). And you can learn more about the usage in [Running the test app](#running-the-test-app).

### Troubleshooting

If you see an error saying that CSS can't be imported from `node_modules` in the `pages` directory. Add the following config to `next.config.js`:

```js copy
transpilePackages: ['react-tweet']
```

The error won't happen if the App Router is enabled, where [Next.js supports CSS imports from `node_modules`](https://github.com/vercel/next.js/discussions/27953#discussioncomment-3978605).

### Enabling cache

It's recommended to enable cache for the Twitter API if you intend to go to production. This is how you can do it with [`unstable_cache`](https://nextjs.org/docs/app/api-reference/functions/unstable_cache):

```tsx
import { Suspense } from 'react'
import { unstable_cache } from 'next/cache'
import { TweetSkeleton, EmbeddedTweet, TweetNotFound } from 'react-tweet'
import { getTweet as _getTweet } from 'react-tweet/api'

const getTweet = unstable_cache(
  async (id: string) => _getTweet(id),
  ['tweet'],
  { revalidate: 3600 * 24 },
)

const TweetPage = async ({ id }: { id: string }) => {
  try {
    const tweet = await getTweet(id)
    return tweet ? <EmbeddedTweet tweet={tweet} /> : <TweetNotFound />
  } catch (error) {
    console.error(error)
    return <TweetNotFound error={error} />
  }
}

const Page = ({ params }: { params: { tweet: string } }) => (
  <Suspense fallback={<TweetSkeleton />}>
    <TweetPage id={params.tweet} />
  </Suspense>
)

export default Page
```

This can prevent getting your server IPs rate limited if they are making too many requests to the Twitter API.

## Advanced usage

### Manual data fetching

You can use the [`getTweet`](/api-reference#gettweet) function from `react-tweet/api` to fetch the tweet manually. This is useful for SSG pages and for other [Next.js data fetching methods](https://nextjs.org/docs/basic-features/data-fetching/overview) in the `pages` directory.

For example, using `getStaticProps` in `pages/[tweet].tsx` to fetch the tweet and send it as props to the page component:

```tsx copy
import { useRouter } from 'next/router'
import { getTweet, type Tweet } from 'react-tweet/api'
import { EmbeddedTweet, TweetSkeleton } from 'react-tweet'

export async function getStaticProps({
  params,
}: {
  params: { tweet: string }
}) {
  const tweetId = params.tweet

  try {
    const tweet = await getTweet(tweetId)
    return tweet ? { props: { tweet } } : { notFound: true }
  } catch (error) {
    return { notFound: true }
  }
}

export async function getStaticPaths() {
  return { paths: [], fallback: true }
}

export default function Page({ tweet }: { tweet: Tweet }) {
  const { isFallback } = useRouter()
  return isFallback ? <TweetSkeleton /> : <EmbeddedTweet tweet={tweet} />
}
```

### Adding `next/image`

Add the domain URLs from Twitter to [`images.remotePatterns`](https://nextjs.org/docs/api-reference/next/image#remote-patterns) in `next.config.js`:

```js copy
/** @type {import('next').NextConfig} */
const nextConfig = {
  images: {
    remotePatterns: [
      { protocol: 'https', hostname: 'pbs.twimg.com' },
      { protocol: 'https', hostname: 'abs.twimg.com' },
    ],
  },
}
```

In `tweet-components.tsx` or elsewhere, import the `Image` component from `next/image` and use it to define custom image components for the tweet:

```tsx copy
import Image from 'next/image'
import type { TwitterComponents } from 'react-tweet'

export const components: TwitterComponents = {
  AvatarImg: (props) => <Image {...props} />,
  MediaImg: (props) => <Image {...props} fill unoptimized />,
}
```

Then pass the `components` prop to `Tweet`:

```tsx copy
import { Tweet } from 'react-tweet'
import { components } from './tweet-components'

export default function Page() {
  return <Tweet id="1628832338187636740" components={components} />
}
```

## Running the test app

Clone the [`react-tweet`](https://github.com/vercel/react-tweet) repository and then run the following command:

```bash copy
pnpm install && pnpm dev --filter=next-app...
```

The app will be up and running at http://localhost:3001 for the [Next.js app example](https://github.com/vercel/react-tweet/tree/main/apps/next-app).

The app shows the usage of `react-tweet` in different scenarios:

- [localhost:3001/light/1629307668568633344](http://localhost:3001/light/1629307668568633344) renders the tweet in the app router.
- [localhost:3001/dark/1629307668568633344](http://localhost:3001/dark/1629307668568633344) renders the tweet using SSG in the pages directory.
- [localhost:3001/light/mdx](http://localhost:3001/light/mdx) rendes the tweet in MDX (with the experimental `mdxRs` config enabled).
- [localhost:3001/light/suspense/1629307668568633344](http://localhost:3001/light/suspense/1629307668568633344) renders the tweet with a custom `Suspense` wrapper.
- [localhost:3001/dark/swr/1629307668568633344](http://localhost:3001/dark/swr/1629307668568633344) uses `apiUrl` to change the API endpoint from which the tweet is fetched in SWR mode.
- [localhost:3001/light/cache/1629307668568633344](http://localhost:3001/light/suspense/1629307668568633344) renders the tweet while caching the tweet data with [`unstable_cache`](https://nextjs.org/docs/app/api-reference/functions/unstable_cache).
- [localhost:3001/light/vercel-kv/1629307668568633344](http://localhost:3001/light/suspense/1629307668568633344) renders the tweet while caching the tweet data with [Vercel KV](https://vercel.com/docs/storage/vercel-kv).

The source code for `react-tweet` is imported from [packages/react-tweet](https://github.com/vercel/react-tweet/tree/main/packages/react-tweet) and any changes you make to it will be reflected in the app immediately.
